package team3;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;

/**Primary Human Interface to a running Reversi Game.
 * <p>
 * Displays the current board state, along with other relevant information
 * (background color reflects current players turn, if selected, the last move
 * played, along with all available moves will be shown, etc).
 * <p>
 * Also provides an interface for Human players, in that, if the current AI is
 * human, the panel will convert mouse click coordinates to game (8x8) coordinates,
 * and tell that human AI to make that move.
 */
public class ReversiPanel extends JPanel implements GameListener, MouseListener
{
	private GameManager manager;
	private ReversiGUI parent;
	private boolean showMoves;
	private int[] lastMove;
    private boolean gameOver;
    private AI.Player winner;

    /**Builds the Reversi Panel, sets the Panel up as a listener to the game manager.
     * @param manager The Game Manager that the panel will be listening to.
     * @param parent The ReversiGUI that spawned this panel.
     * @param showMoves Whether or not the panel should show moves available to the current player.
     */
	public ReversiPanel(GameManager manager, ReversiGUI parent, boolean showMoves)
	{
		lastMove=BoardState.INVALID_MOVE;
		this.manager=manager;
		this.parent=parent;
		this.showMoves=showMoves;
		manager.registerGameListener(this);
		this.addMouseListener(this);
	}

    /** Paints the 8x8 Reversi Board, along with relevant associated information.
     */
    @Override
	public void paint(Graphics g)
	{
		AI.Player[][] currentState = manager.getBoard().getState();
		AI.Player currentPlayer = manager.getCurrentAI().getPlayer();

        //paint the background in the color of the current player
		g.setColor(getColor(currentPlayer));
		g.fillRect(0, 0, getWidth(), getHeight());

        //determine how tall and how wide a single stone/peice is.
		int dy = getHeight()/currentState.length;
		int dx = getWidth()/currentState[0].length;
        //draw each occupied square
		for(int r=0; r<currentState.length; r++)
			for(int c=0; c<currentState[r].length; c++)
			{
				AI.Player currentSquare = currentState[r][c];
				if(currentSquare==AI.Player.EMPTY)
					continue;
				Color peiceColor = getColor(currentSquare);
				if(lastMove[0]==r&&lastMove[1]==c&&showMoves)
						peiceColor=Color.GRAY;
                //draw the peice, with a red outline
				drawPeice(g, r, c, dx, dy, Color.RED, peiceColor);
			}

        //draw possible moves for the current player
		if(showMoves)
			for(int[] move : manager.getBoard().getAvailableMoves(currentPlayer))
				drawPeice(g, move[0], move[1], dx, dy, Color.GREEN, Color.BLUE);

        if(gameOver)
            drawWinnerText(g);
	}

    /**Draws text detailing who won the game.
     */
    private void drawWinnerText(Graphics g)
    {
        String msg="";
        switch(winner)
        {
            case BLACK: msg="BLACK WINS"; break;
            case WHITE: msg="WHITE WINS"; break;
            case EMPTY: msg="TIE"; break;
        }
        g.setColor(Color.BLUE);
        g.setFont(new Font("Arial", Font.BOLD, 46));
        g.drawString(msg, getWidth()/6, getHeight()/2);
    }

    /** Determines the color associated with a player
     * @param player Either black of white player
     * @return Color.Black or Color.White.
     */
	private Color getColor(AI.Player player)
	{
		if(player==AI.Player.BLACK)
			return Color.BLACK;
		return Color.WHITE;
	}

    /** Draws a stone to screen.
     * @param r Row the stone is in
     * @param c Column the stone is in
     * @param dx Width of a single stone in pixels
     * @param dy Height of a single stone in pixels
     * @param ring Color of the ring arround the peice
     * @param circle Color of the peice
     */
	private void drawPeice(Graphics g, int r, int c, int dx, int dy, Color ring, Color circle)
	{
		int x=c*dx;
		int y=r*dy;
		g.setColor(ring);
		g.fillOval(x+1, y+1, dx-2, dy-2);
		g.setColor(circle);
		g.fillOval(x+3, y+3, dx-6, dy-6);
	}

    /**Handler for nextPlayersTurn, triggers a repaint of the panel.
     * @param game GameManager that fired the event.
     * @param currentPlayer Player whose turn it now is
     * @param lastMove Last move made
     * @see GameListener#nextPlayersTurn(team3.GameManager, project2.AI.Player, int[]) 
     */
	public void nextPlayersTurn(GameManager game, AI.Player currentPlayer, int[] lastMove)
	{
		this.lastMove=lastMove;
		repaint();
	}

    /**Handler for gameOver. Triggers a repaint, and logs who won and lost.
     * @param game GameManager that fired the event.
     * @param winner Player who won.
     */
	public void gameOver(GameManager game, AI.Player winner)
	{
        gameOver=true;
        this.winner=winner;
		repaint();
	}

    /** Determines which space was clicked, and, if the current AI is a human,
     * tells the human to try moving there.
     */
	public void mouseClicked(MouseEvent e)
	{
		project2.AI currentAI = manager.getCurrentAI();
		if(currentAI instanceof Human)
		{
			AI.Player[][] state = manager.getBoard().getState();
			int dy=getHeight()/state.length;
			int row = e.getY()/dy;
			int dx=getWidth()/state.length;
			int col = e.getX()/dx;
			((Human)currentAI).move(new int[]{row, col});
		}
	}

	/**unused portions of mouse listener*/
	public void mousePressed(MouseEvent e){}
	/**unused portions of mouse listener*/
	public void mouseReleased(MouseEvent e){}
	/**unused portions of mouse listener*/
	public void mouseEntered(MouseEvent e){}
	/**unused portions of mouse listener*/
	public void mouseExited(MouseEvent e){}
}
